﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EPiBoost.Core.Helpers;
using EPiServer.Data.Entity;

namespace EPiBoost.Core.CustomProperties.EnumSelector
{
	[Serializable]
	public class SelectedEnumCollection<T> : IEnumerable<SelectedEnum<T>>, IReadOnly<SelectedEnumCollection<T>> where T : struct
	{
		private bool isReadOnly;
        private bool isModified;
		private List<SelectedEnum<T>> values;

		public SelectedEnumCollection()
        {
			values = new List<SelectedEnum<T>>();
        }

		public IEnumerator<SelectedEnum<T>> GetEnumerator()
        {
            return values.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public bool IsModified
        {
            get
            {
                return isModified;
            }
            set
            {
                ThrowIfReadyOnly();
                isModified = value;
            }
        }

        private void ThrowIfReadyOnly()
        {
            if (IsReadOnly)
                throw new NotSupportedException("The list of keywords is read-only.");
        }

        public override bool Equals(object obj)
        {

			var compareTo = obj as SelectedEnumCollection<T>;

            if (compareTo == null)
                return false;

            return values.SequenceEqual(compareTo.values);
        }

        public override string ToString()
        {
            return CommaSeparatedStringHelper.Concatenate(values.Select(x=>x.Value.ToString()));
        }

		public static SelectedEnumCollection<T> Parse(string value)
        {
            if(value == null)
                throw new ArgumentException(
					"Cannot parse SelectedEnumCollection<T> objects from null",
                    "value");

			var result = new SelectedEnumCollection<T>();
            var enumStrings = CommaSeparatedStringHelper.Parse(value);
			foreach (var str in enumStrings)
			{
				result.values.Add(EnumHelper.GetSelectedEnumFromString<T>(str));
			}
            return result;
        }

		public SelectedEnumCollection<T> CreateWritableClone()
        {
			var copy = new SelectedEnumCollection<T>();
			copy.values = new List<SelectedEnum<T>>(values);
            copy.isReadOnly = false;
            
            return copy;
        }

		object IReadOnly.CreateWritableClone()
		{
			return CreateWritableClone();
		}

        public void MakeReadOnly()
        {
            isReadOnly = true;
        }


		public bool IsReadOnly
        {
            get { return isReadOnly; }
        }

		public SelectedEnumCollection<T> Copy()
        {
			var copy = (SelectedEnumCollection<T>)MemberwiseClone();

			copy.values = new List<SelectedEnum<T>>(values);

            return copy;
        }

		public void Add(SelectedEnum<T> value)
        {
            ThrowIfReadyOnly();

            isModified = true;

            values.Add(value);
        }

		public static explicit operator SelectedEnumCollection<T>(string input)
		{
			return Parse(input);
		}
		 
	}
}
